#pragma once

#include <iostream>
#include <vector>
#include <string>
#include <sys/types.h>
#include <sys/stat.h>
#include <cerrno>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <fcntl.h>
#include <memory>

#include "task.hpp"
using namespace std;


enum Error
{
    ArgcError = 1,
    ProcessNumError
};

//命名管道名字组
vector<string> pipe_name{"pipe1", "pipe2", "pipe3"};
#define Mode 0666
#define Path "./default"


class Fifo
{
public:
    Fifo(string path = Path, int mode = Mode)
        :_path(path)
        ,_mode(mode)
    {}

    void CreateNamePipe()
    {
        int return_mkfifo_val = mkfifo(_path.c_str(),_mode);
        if(return_mkfifo_val < 0)
        {
            cout << "mkfifo error:" << errno << " reason :" << strerror(errno) << endl;
            exit(1);
        }

        cout << "mkfifo success" << endl;
    }

    ~Fifo()
    {
        int return_unlink_val = unlink(_path.c_str());
        if(return_unlink_val < 0)
        {
            cout << "unlink error:" << errno << " reason :" << strerror(errno) << endl;
        }

        cout << "unlink namepipe success" << endl;
    }

private:
    string _path;
    int _mode;
};

//父进程与子进程进行通信的管道
class Channal
{

public:

    Channal(int wfd, int process_pid, string& pipe_name)
        :_wfd(wfd)
        ,_process_pid(process_pid)
        ,_pipe_name(pipe_name)
    {}

    ~Channal()
    {}

    int get_wfd() 
    {
        return _wfd;
    }

    int get_process_pid()
    {
        return _process_pid;
    }

    string get_pipe_name()
    {
        return _pipe_name;
    }

private:
    int _wfd;          //父进程要写入的管道
    int _process_pid;  //子进程pid
    string _pipe_name; //管道名字

};

class ProcessPool
{

public:
    ProcessPool(int processnum)
        :_processnum(processnum)
    {
        
    }
    

    void MakePipeName()
    {
        pipe_name.clear();
        for(int i=0; i<_processnum; i++)
        {
            string s;
            cout << "输入第" << i << "个管道名字: "; 
            getline(cin, s);

            pipe_name.push_back(s);
        }
    }

    void Random_MakePipeName()
    {
        pipe_name.clear();

        for(int i=0; i<_processnum; i++)
        {
            string s;
            s += "pipe" + to_string(i+1);

            pipe_name.push_back(s);
        }
    }

    void CreateProcessPool(work_t work)
    {
        for(int i=0; i<_processnum; i++)
        {
            // //父进程创建命名管道
            vsf.push_back(new Fifo(pipe_name[i]));
            vsf[i]->CreateNamePipe();

            int id = fork();
            if(id == 0)
            {
                //子进程
                int rfd = open(pipe_name[i].c_str(),O_RDONLY);
                work(rfd);

                exit(0);
            }

            //父进程打开管道,未发送任务
            int wfd = open(pipe_name[i].c_str(), O_WRONLY);
            _processpool.push_back({wfd,id,pipe_name[i]});
        }  
    }

    int rand_pipe()
    {
        static int pipe_code = 0;
        int return_code = pipe_code;

        pipe_code++;
        pipe_code %= _processnum;

        return return_code;
    }

    int rand_work()
    {
        return rand() % 3;
    }

    void RunTask(ProcessPool* processpool)
    {
        int cnt = 10;

        while(cnt--)
        {
            //随机选中管道
            int luck_pipe = processpool->rand_pipe();

            //随机选中工作
            int luck_work = processpool->rand_work();

            //父进程向管道发送任务
            processpool->send_task(luck_pipe, luck_work);

            sleep(1);
        }
    }

    void send_task(int wfd, int task)
    {
        cout << "send task to : " << _processpool[wfd].get_wfd() << endl;
        write(_processpool[wfd].get_wfd(), &task, sizeof(task));
    }

    ~ProcessPool()
    {
        for(int i=0; i<_processnum; i++)
        {
            delete vsf[i];
        }
    }

private:
    int _processnum;
    vector<Channal> _processpool;
    vector<Fifo*> vsf;
};